<?php
/*
	Copyright (C) 2008 - 2013 Inanta Martsanto
	Inanta Martsanto (inanta@inationsoft.com)

	This file is part of NewStep Framework.

	NewStep Framework is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	NewStep Framework is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with NewStep Framework.  If not, see <http://www.gnu.org/licenses/>.
*/

namespace Inationsoft\NS;

/**
 *Handle date and time manipulation
 *
 *@author Inanta Martsanto <inanta@inationsoft.com>
 *@property int $Date Represent date
 *@property int $Month Represent month
 *@property int $Year Represent year
 *@property int $TwoDigitYear Represent year in 2 digit
 *@property int $Hour Represent hour
 *@property int $Minute Represent minute
 *@property int $Second Represent second
 *@property int $Timestamp Represent timestamp
 *@property int $IsLeapYear Represent whenever current year is leap year
 */

class DateTime extends Object {
	private $_timestamp;

	function __construct($date = null, $month = null, $year = null) {
		if($date != null && $month != null && $year != null) {
			$this->_timestamp = mktime(0, 0, 0, $month, $date, $year);
		} else {
			$this->_timestamp = time();	
		}

		$this->createProperties(array('Date' => date('j', $this->_timestamp), 'Month' => date('n', $this->_timestamp), 'Year' => date('Y', $this->_timestamp), 'TwoDigitYear' => date('y', $this->_timestamp),
			'Hour' => date('h', $this->_timestamp), 'Minute' => date('i', $this->_timestamp), 'Second' => date('s', $this->_timestamp),
			'Timestamp' => $this->_timestamp));

		$this->createProperties(array('IsLeapYear' => DateTime::isLeapYear($this->Year)));
	}

	function __get($property) {
		switch($property) {
			case 'DayStartTime':
				return mktime(0, 0, 0, $this->Month, $this->Date, $this->Year);
			case 'DayEndTime':
				return mktime(23, 59, 59, $this->Month, $this->Date, $this->Year);
			case 'MonthStartTime':
				return mktime(0, 0, 0, $this->Month, 1, $this->Year);
			case 'MonthEndTime':
				return (in_array($this->Month, array(1, 3, 5, 7, 8, 10)) ? mktime(23, 59, 59, $this->Month, 31, $this->Year) : (in_array($this->Month, array(4, 6, 9, 11) ? mktime(23, 59, 59, $this->Month, 30, $this->Year) : (self::isLeapYear($this->Year) ? mktime(23, 59, 59, $this->Month, 29, $this->Year) : mktime(23, 59, 59, $this->Month, 28, $this->Year)))));
			case 'YearStartTime':
				return mktime(0, 0, 0, 1, 1, $this->Year);
			case 'YearEndTime':
				return mktime(23, 59, 59, 12, 31, $this->Year);
			default:
				return parent::__get($property);
		}
	}

	function __set($property, $value) {
		if($property == 'Timestamp') { $this->_timestamp = $value; $this->assignDateTimeValue(); }
		
		parent::__set($property, $value);
	}

	function addSeconds($sec) { $this->Timestamp += $sec; }
	function addMinutes($min) { $this->Timestamp += ($min * 60); }
	function addHours($hour) { $this->Timestamp += ($hour * 3600); }
	function addDays($day) { $this->Timestamp += ($day * 86400); }
	function addWeeks($week) { $this->Timestamp += ($week * 604800); }

	function addMonths($month) {
		while($month >= 12) {
			$this->addYears(1);
			$month -= 12;
		}
		$timestamp = 0;
		for($i = 0; $i < $month; ++$i) {
			switch(($this->Month + $i) % 12) {
				case 1:
					if($i != 0) $this->Year += 1;
				case 3: case 5: case 7:
				case 8: case 10: case 0:
					$timestamp += 2678400; break;
				case 4: case 6: case 9: case 11:
					$timestamp += 2592000; break;
				case 2:
					if(DateTime::isLeapYear($this->Year)) $timestamp += 2505600;
					else $timestamp += 2419200;
			}
		}
		if($timestamp != 0) $this->Timestamp += $timestamp;
	}

	function addYears($year) {
		$i = 0; if($this->Month > 2) { ++$i; $year += 1; }
		$timestamp = 0;
		for($i; $i < $year; ++$i) {
			$timestamp += (!DateTime::isLeapYear($this->Year + $i) ? 31536000 : 31622400);
		}
		$this->Timestamp += $timestamp;
	}

	function __toString() {
		return date('d/n/Y', $this->_timestamp);
	}

	static function fromString($date) {
		$part = explode('/', $date);
		if(count($part) !== 3) throw new Exception();
		
		return new DateTime($part[0], $part[1], $part[2]);
	}
	
	static function fromTimestamp($timestamp) {
		$dt = new DateTime();
		$dt->Timestamp = $timestamp;
		
		return $dt; 
	}

	static function isLeapYear($year) {
		return ($year % 400 == 0 ? true : ($year % 100 == 0 ? true : ($year % 4 == 0 ? true : false)));	
	}

	private function assignDateTimeValue() {
		$this->Date = date('j', $this->_timestamp);
		$this->Month = date('n', $this->_timestamp);
		$this->Year = date('Y', $this->_timestamp);
		$this->Hour = date('h', $this->_timestamp);
		$this->Minute = date('i', $this->_timestamp);
		$this->Second = date('s', $this->_timestamp);
		$this->IsLeapYear = ($this->Year % 400 == 0 ? true : ($this->Year % 100 == 0 ? true : ($this->Year % 4 == 0 ? true : false)));
	}
}
?>